package com.mzy.basics.utils.JsonUtils;

/**
 * @author Ives
 * * @date 2022/2/16
 */

import cn.ipokerface.common.utils.StringEscapeUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import com.mzy.basics.utils.Java.StringUtil;
import com.mzy.basics.utils.Java.SystemException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * <p>Title: JsonUtil</p>
 * <p>Description:JOSN处理工具类</p>
 *
 * @author lins
 * @date 2019年06月05日 16:23:59
 */
@Slf4j
@SuppressWarnings("unchecked")
public final class JsonUtil {

  public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

  private JsonUtil() {
  }

  public static String toJsonString(Object object) {
    try {
      return OBJECT_MAPPER.writeValueAsString(object);
    } catch (JsonProcessingException e) {
      log.error(e.getMessage(), e);
      throw new SystemException(e);
    }
  }

  public static Map<String, Object> jsonStrToMap(String jsonStr) {
    if (!StringUtils.hasText(jsonStr)) {
      return Maps.newHashMap();
    }
    Map<String, Object> map = null;
    try {
      map = OBJECT_MAPPER.readValue(jsonStr, Map.class);
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new SystemException(e);
    }
    return map;
  }

  /**
   * valid content is Json no not，
   *
   * @param content
   * @return true by default
   */
  public static boolean checkIfJson(String content) {
    if (StringUtil.isBlank(content)) {
      return false;
    }
    boolean valid = true;
    try {
      TypeReference<HashMap<String, Object>> typeRef
              = new TypeReference<HashMap<String, Object>>() {
      };
      ObjectMapper mapper = new ObjectMapper();
      mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
      mapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
      content = StringEscapeUtils.unescapeJava(content);
      mapper.readValue(content, typeRef);
    } catch (Exception e) {
      valid = false;
    }
    return valid;
  }

  /**
   * check is empty Json
   *
   * @param content
   * @return false by default
   */
  public static boolean isEmptyJson(String content) {
    if (StringUtil.isBlank(content)) {
      return false;
    }
    ObjectMapper mapper = new ObjectMapper();
    try {
      content = StringEscapeUtils.unescapeJava(content);
      JsonNode jsonNode = mapper.readTree(content);
      Iterator<JsonNode> it = jsonNode.iterator();
      if (it.next() == null) {
        if (jsonNode.isObject() || jsonNode.isEmpty(null)) {
          return true;
        }
      } else {
        while (it.hasNext()) {
          JsonNode node = it.next();
          if (node.isObject() || node.isEmpty(null)) {
            return true;
          }
        }
      }
    } catch (Exception e) {
      return false;
    }
    return false;
  }

  /**
   * Json to Object
   *
   * @param content
   * @param clazz
   * @param <T>
   * @return null, need valid if return null
   */
  public static <T> T jsonToObject(String content, Class<T> clazz) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
    content = StringEscapeUtils.unescapeJava(content);
    try {
      return mapper.readValue(content, clazz);
    } catch (Exception e) {
      return null;
    }
  }

  public static void main(String[] args) {
    String str = "{\"name\":\"张三\",\"age\":23,\"addr\":{\"province\":\"广东\",\"city\":\"珠海\",\"area\":\"香洲\"},\"hobby\":[\"电影\",\"旅游\"]}";
    Map<String, Object> stringObjectMap = jsonStrToMap(str);
    String s = stringObjectMap.entrySet().toString();
    stringObjectMap.forEach((k,v) -> System.out.println(k+v));
    System.out.println(s);
  }

}
